﻿using System;
using System.Threading;
using System.Threading.Tasks;

namespace Zo.Events
{
    /// <summary>
    /// 事件总线。
    /// </summary>
    public interface IEventBus : IEventPublisher, IEventSubscriber
    {
    }

    public abstract class EventBusBase : IEventBus
    {
        protected readonly IEventHandlerExecutor _EventHandlerExecutor;

        protected EventBusBase(IEventHandlerExecutor EventHandlerExecutor)
        {
            _EventHandlerExecutor = EventHandlerExecutor;
        }

        ~EventBusBase()
        {
            Dispose(false);
        }

        public abstract IEventResult Publish<TEvent>(TEvent @event) where TEvent : IEvent;

        public abstract Task PublishAsync<TEvent>(TEvent @event, CancellationToken cancellationToken = default) where TEvent : IEvent;

        public virtual void Subscribe<TEvent, TEventHandler>()
            where TEvent : class, IEvent
            where TEventHandler : class, IEventHandler<TEvent>
        {
            Subscribe(typeof(TEvent), typeof(TEventHandler));
        }

        public virtual void Subscribe(Type eventType, Type handlerType)
        {
            if (!typeof(IEvent).IsAssignableFrom(eventType))
            {
                return;
            }

            if (!typeof(IEventHandler).IsAssignableFrom(handlerType))
            {
                return;
            }

            OnSubscribe(eventType, handlerType);
        }

        public abstract void OnSubscribe(Type eventType, Type handlerType);

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
        }
    }
}